package com.market.domain;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;
import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.Table;
import javax.persistence.Transient;

@Entity
@Table(name = "weekly")
public class Weekly extends BaseObject implements Comparable<Weekly> {

	@Override
	public boolean equalsId(Object o) {
		if ((o instanceof Weekly) && ((Weekly) o).getId().equals(this.id)) {
			return true;
		}

		return false;
	}
	
	@Transient
	private List<Product> inStockNotInWeeklyProducts;
	
	
	
	public List<Product> getInStockNotInWeeklyProducts() {
		return inStockNotInWeeklyProducts;
	}

	public void setInStockNotInWeeklyProducts(
			List<Product> inStockNotInWeeklyProducts) {
		this.inStockNotInWeeklyProducts = inStockNotInWeeklyProducts;
	}

	@Transient
	private List<ProductPrice> filteredProductPrices;
	

	public List<ProductPrice> getFilteredProductPrices() {
		return filteredProductPrices;
	}

	public void setFilteredProductPrices(List<ProductPrice> filteredProductPrices) {
		this.filteredProductPrices = filteredProductPrices;
	}

	@Transient
	public String getTitleLabel() {
		return super.getLabel("Title", super.getLocale());
	}

	@Transient
	public String getCommentsLabel() {
		return super.getLabel("Comments", super.getLocale());
	}

	@Transient
	public String getStartDateLabel() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		return format.format(this.getStartDate());
	}

	@Transient
	public String getEndDateLabel() {
		SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
		return format.format(this.getEndDate());
	}

	@Transient
	public Date getStartDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.THURSDAY);
		calendar.set(Calendar.YEAR, this.year);
		calendar.set(Calendar.WEEK_OF_YEAR, this.weekOfYear);
		calendar.set(Calendar.DAY_OF_WEEK, Calendar.THURSDAY);
		return calendar.getTime();
	}

	@Transient
	public Date getEndDate() {
		Calendar calendar = Calendar.getInstance();
		calendar.setFirstDayOfWeek(Calendar.THURSDAY);
		calendar.set(Calendar.YEAR, this.year);
		calendar.set(Calendar.WEEK_OF_YEAR, this.weekOfYear);
		calendar.set(Calendar.DAY_OF_WEEK, Calendar.WEDNESDAY);
		return calendar.getTime();
	}

	public int compareTo(Weekly o) {
		if (this.year > o.getYear() || this.year.equals(o.getYear())
				&& this.weekOfYear > o.getWeekOfYear()) {
			return 1;
		} else {
			if (this.year < o.getYear() || this.year.equals(o.getYear())
					&& this.weekOfYear < o.getWeekOfYear()) {
				return -1;
			} else {
				return 0;
			}
		}
	}

	@Transient
	public String getLabel() {
		return this.getStartDateLabel() + "- " + this.getEndDateLabel();
	}

	public List<ProductPrice> getFruitList() {
		return fruitList;
	}

	public void setFruitList(List<ProductPrice> fruitList) {
		this.fruitList = fruitList;
	}

	@Transient
	public Boolean getIsFruitListEmpty() {
		return (this.fruitList == null || this.fruitList.size() == 0);
	}

	public List<ProductPrice> getVegetableList() {
		return vegetableList;
	}

	public void setVegetableList(List<ProductPrice> vegetableList) {
		this.vegetableList = vegetableList;
	}

	@Transient
	public Boolean getIsVegetableListEmpty() {
		return (this.vegetableList == null || this.vegetableList.size() == 0);
	}

	public List<ProductPrice> getOtherProductList() {
		return otherProductList;
	}

	public void setOtherProductList(List<ProductPrice> otherProductList) {
		this.otherProductList = otherProductList;
	}

	@Transient
	public Boolean getIsNotFreshListEmpty() {
		return (this.otherProductList == null || this.otherProductList.size() == 0);
	}

	public List<ProductPrice> getToFuList() {
		return toFuList;
	}

	public void setToFuList(List<ProductPrice> toFuList) {
		this.toFuList = toFuList;
	}
	

	public List<ProductPrice> getMeatList() {
		return MeatList;
	}

	public void setMeatList(List<ProductPrice> meatList) {
		MeatList = meatList;
	}

	
	public List<ProductPrice> getSauceList() {
		return sauceList;
	}

	public void setSauceList(List<ProductPrice> sauceList) {
		this.sauceList = sauceList;
	}

	public List<ProductPrice> getSeasoningList() {
		return seasoningList;
	}

	public void setSeasoningList(List<ProductPrice> seasoningList) {
		this.seasoningList = seasoningList;
	}

	public List<ProductPrice> getSpicyList() {
		return spicyList;
	}

	public void setSpicyList(List<ProductPrice> spicyList) {
		this.spicyList = spicyList;
	}

	public List<ProductPrice> getSnackList() {
		return snackList;
	}

	public void setSnackList(List<ProductPrice> snackList) {
		this.snackList = snackList;
	}

	public List<ProductPrice> getDriedFoodList() {
		return driedFoodList;
	}

	public void setDriedFoodList(List<ProductPrice> driedFoodList) {
		this.driedFoodList = driedFoodList;
	}

	public Boolean getIsSauceListEmpty() {
		return (this.sauceList == null || this.sauceList.size() == 0);
	}

	public Boolean getIsSeasoningListEmpty() {
		return (this.seasoningList == null || this.seasoningList.size() == 0);
	}

	public Boolean getIsSpicyListEmpty() {
		return (this.spicyList == null || this.spicyList.size() == 0);
	}

	public Boolean getIsSnackListEmpty() {
		return (this.snackList == null || this.snackList.size() == 0);
	}

	public Boolean getIsDriedFoodListEmpty() {
		return (this.driedFoodList == null || this.driedFoodList.size() == 0);
	}
	
	public Boolean getIsMeatListEmpty() {
		return (this.MeatList == null || this.MeatList.size() == 0);
	}

	@Transient
	public Boolean getIsToFuListEmpty() {
		return (this.toFuList == null || this.toFuList.size() == 0);
	}

	public List<ProductPrice> getClearanceProductList() {
		return clearanceProductList;
	}

	public void setClearanceProductList(List<ProductPrice> clearanceProductList) {
		this.clearanceProductList = clearanceProductList;
	}

	@Transient
	public Boolean getIsClearanceListEmpty() {
		return (this.clearanceProductList == null || this.clearanceProductList
				.size() == 0);
	}

	public Product.TYPE getCurrentType() {
		return currentType;
	}

	public void setCurrentType(Product.TYPE currentType) {
		this.currentType = currentType;
	}

	/**
	 * Return product type according to currentTyp.
	 * @return
	 */
	
	public List<ProductPrice> getCurrentProductList() {
		switch (currentType) {
		case LEAF_VEGETABLE:
			return this.vegetableList;
		case FRUIT_VEGETABLE:
			return this.vegetableList;
		case ROOT_VEGETABLE:
			return this.vegetableList;
		case STEM_VEGETABLE:
			return this.vegetableList;
		case OTHER_VEGETABEL:
			return this.vegetableList;
		case FRUIT:
			return this.fruitList;
		case TOFU:
			return this.toFuList;
		case NOODLE:
			return this.otherProductList;
		case BAKERY:
			return this.otherProductList;
		case SAUCE:
			return this.sauceList;
		case SEASONING:
			return this.seasoningList;
		case SPICY:
			return this.spicyList;
		case SNACK:
			return this.snackList;
		case DRIED_FOOD:
			return this.driedFoodList;
		case FROZEN_FOOD:
			return this.otherProductList;
		case MEAT:
			return this.otherProductList;
		case PREPARED_FOOD:
			return this.otherProductList;
		case PRESERVED_FOOD:
			return this.otherProductList;
		case CLEARANCE:
			return this.clearanceProductList;
		case OTHER:
			return this.otherProductList;
		}
		return this.otherProductList;
	}

	/**
	 * Invoke when set productPrice property. Put snack and sauce to not fresh
	 * product, clearance go to clearance products, others go to fresh product;
	 */
	private void sortProductPrices() {
		this.vegetableList.clear();
		this.fruitList.clear();
		this.otherProductList.clear();
		this.sauceList.clear();
		this.spicyList.clear();
		this.seasoningList.clear();
		this.snackList.clear();
		this.clearanceProductList.clear();
		this.toFuList.clear();
		for (ProductPrice price : this.productPrices) {
			switch (price.getProduct().getType()) {
			case LEAF_VEGETABLE:
				this.vegetableList.add(price);
				break;
			case FRUIT_VEGETABLE:
				this.vegetableList.add(price);
				break;
			case ROOT_VEGETABLE:
				this.vegetableList.add(price);
				break;
			case STEM_VEGETABLE:
				this.vegetableList.add(price);
				break;
			case OTHER_VEGETABEL:
				this.vegetableList.add(price);
				break;
			case FRUIT:
				this.vegetableList.add(price);
				break;
			case TOFU:
				this.toFuList.add(price);
				break;
			case NOODLE:
				this.otherProductList.add(price);
				break;
			case BAKERY:
				this.otherProductList.add(price);
				break;
			case SAUCE:
				this.sauceList.add(price);
				break;
			case SEASONING:
				this.seasoningList.add(price);
				break;
			case SPICY:
				this.spicyList.add(price);
				break;
			case SNACK:
				this.snackList.add(price);
				break;
			case DRIED_FOOD:
				this.driedFoodList.add(price);
				break;
			case FROZEN_FOOD:
				this.otherProductList.add(price);
				break;
			case MEAT:
				this.MeatList.add(price);
				break;
			case PREPARED_FOOD:
				this.otherProductList.add(price);
				break;
			case PRESERVED_FOOD:
				this.otherProductList.add(price);
				break;
			case CLEARANCE:
				this.clearanceProductList.add(price);
				break;
			case OTHER:
				this.otherProductList.add(price);
				break;
			}

			// if (price.getProduct().getType() == TYPE.SNACK
			// || price.getProduct().getType() == TYPE.SAUCE
			// || price.getProduct().getType() == TYPE.PREPARED_FOOD
			// || price.getProduct().getType() == TYPE.NOODLE
			// || price.getProduct().getType() == TYPE.DRIED_FOOD
			// || price.getProduct().getType() == TYPE.OTHER
			// || price.getProduct().getType() == TYPE.PRESERVED_FOOD) {
			// this.notFreshProductList.add(price);
			// } else {
			// if (price.getProduct().getType() == TYPE.CLEARANCE) {
			// this.clearanceProductList.add(price);
			// } else {
			// this.freshProductList.add(price);
			// }
			// }
		}
	}
	
	
	public void setVegetableAsCurrentType(){
		this.currentType = Product.TYPE.LEAF_VEGETABLE;
	}
	
	
	public void setFruitAsCurrentType(){
		this.currentType = Product.TYPE.FRUIT;
	}
	
	public void setTofuAsCurrentType(){
		this.currentType = Product.TYPE.TOFU;
	}
	
	
	public void setSauceAsCurrentType(){
		this.currentType = Product.TYPE.SAUCE;
	}
	
	public void setSeasoningAsCurrentType(){
		this.currentType = Product.TYPE.SEASONING;
	}
	
	public void setSpicyAsCurrentType(){
		this.currentType = Product.TYPE.SPICY;
	}
	
	public void setSnackAsCurrentType(){
		this.currentType = Product.TYPE.SNACK;
	}
	
	
	public void setDriedFoodAsCurrentType(){
		this.currentType = Product.TYPE.DRIED_FOOD;
	}
	
	
	public void setOtherAsCurrentType(){
		this.currentType = Product.TYPE.OTHER;
	}
	public void setClearanceAsCurrentType(){
		this.currentType = Product.TYPE.CLEARANCE;
	}
	

	/**
	 * 
	 */
	private static final long serialVersionUID = 2047468654139419690L;
	@Transient
	private List<ProductPrice> vegetableList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> fruitList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> otherProductList = new ArrayList<ProductPrice>(); // Other
																					// products
	@Transient
	private List<ProductPrice> toFuList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> MeatList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> sauceList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> seasoningList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> spicyList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> driedFoodList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> snackList = new ArrayList<ProductPrice>();
	@Transient
	private List<ProductPrice> clearanceProductList = new ArrayList<ProductPrice>();

	@Transient
	private Product.TYPE currentType = Product.TYPE.LEAF_VEGETABLE;

	@Id
	@GeneratedValue(strategy = GenerationType.AUTO)
	private Long id = 0L;
	@Column(nullable = false)
	private Integer year = 2013;
	@Column(nullable = false)
	private Integer weekOfYear = 1;
	@Column(length = 250)
	private String title;
	@Column(length = 250)
	private String chineseTitle;
	@Column(length = 250)
	private String frenchTitle;
	@Column(length = 1000)
	private String comments;
	@Column(length = 1000)
	private String chineseComments;
	@Column(length = 1000)
	private String frenchComments;
	@Column(columnDefinition = "Long Default 0")
	private Long freeDeliveryMinimumAmount = 18L;	
	@Column(columnDefinition = "Double Default 0")
	private Double deliveryFee = 1.8D;	
	@Column(columnDefinition = "bit(1) default 0")
	private Boolean isActive = Boolean.FALSE;
	@ManyToMany(cascade = javax.persistence.CascadeType.ALL, fetch = FetchType.LAZY)
	private List<ProductPrice> productPrices = new ArrayList<ProductPrice>();

	public Long getId() {
		return id;
	}

	public void setId(Long id) {
		this.id = id;
	}

	public Integer getYear() {
		return year;
	}

	public void setYear(Integer year) {
		this.year = year;
	}

	public Integer getWeekOfYear() {
		return weekOfYear;
	}

	public void setWeekOfYear(Integer weekOfYear) {
		this.weekOfYear = weekOfYear;
	}

	public String getTitle() {
		return title;
	}

	public void setTitle(String title) {
		this.title = title;
	}

	public String getChineseTitle() {
		return chineseTitle;
	}

	public void setChineseTitle(String chineseTitle) {
		this.chineseTitle = chineseTitle;
	}

	public String getFrenchTitle() {
		return frenchTitle;
	}

	public void setFrenchTitle(String frenchTitle) {
		this.frenchTitle = frenchTitle;
	}

	public String getComments() {
		return comments;
	}

	public void setComments(String comments) {
		this.comments = comments;
	}

	public String getChineseComments() {
		return chineseComments;
	}

	public void setChineseComments(String chineseComments) {
		this.chineseComments = chineseComments;
	}

	public String getFrenchComments() {
		return frenchComments;
	}

	public void setFrenchComments(String frenchComments) {
		this.frenchComments = frenchComments;
	}

	public Boolean getIsActive() {
		return isActive;
	}

	public void setIsActive(Boolean isActive) {
		this.isActive = isActive;
	}


	public List<ProductPrice> getProductPrices() {
		return productPrices;
	}
	
	public Long getFreeDeliveryMinimumAmount() {
		return freeDeliveryMinimumAmount;
	}

	public void setFreeDeliveryMinimumAmount(Long freeDeliveryMinimumAmount) {
		this.freeDeliveryMinimumAmount = freeDeliveryMinimumAmount;
	}

	public Double getDeliveryFee() {
		return deliveryFee;
	}

	public void setDeliveryFee(Double deliveryFee) {
		this.deliveryFee = deliveryFee;
	}

	/**
	 * At the same time sort product to fresh, notFresh, and clearance
	 * 
	 * @param productPrices
	 */
	public void setProductPrices(List<ProductPrice> productPrices) {
		this.productPrices = productPrices;
		this.sortProductPrices();
	}

	@Override
	public int hashCode() {
		final int prime = 31;
		int result = 1;
		result = prime * result
				+ ((chineseComments == null) ? 0 : chineseComments.hashCode());
		result = prime * result
				+ ((chineseTitle == null) ? 0 : chineseTitle.hashCode());
		result = prime * result
				+ ((comments == null) ? 0 : comments.hashCode());
		result = prime * result
				+ ((frenchComments == null) ? 0 : frenchComments.hashCode());
		result = prime * result
				+ ((frenchTitle == null) ? 0 : frenchTitle.hashCode());
		result = prime * result
				+ ((weekOfYear == null) ? 0 : weekOfYear.hashCode());
		result = prime * result + ((title == null) ? 0 : title.hashCode());
		result = prime * result + ((year == null) ? 0 : year.hashCode());
		return result;
	}

	@Override
	public boolean equals(Object obj) {
		if (this == obj)
			return true;
		if (obj == null)
			return false;
		if (getClass() != obj.getClass())
			return false;
		Weekly other = (Weekly) obj;
		if (chineseComments == null) {
			if (other.chineseComments != null)
				return false;
		} else if (!chineseComments.equals(other.chineseComments))
			return false;
		if (chineseTitle == null) {
			if (other.chineseTitle != null)
				return false;
		} else if (!chineseTitle.equals(other.chineseTitle))
			return false;
		if (comments == null) {
			if (other.comments != null)
				return false;
		} else if (!comments.equals(other.comments))
			return false;
		if (frenchComments == null) {
			if (other.frenchComments != null)
				return false;
		} else if (!frenchComments.equals(other.frenchComments))
			return false;
		if (frenchTitle == null) {
			if (other.frenchTitle != null)
				return false;
		} else if (!frenchTitle.equals(other.frenchTitle))
			return false;
		if (weekOfYear == null) {
			if (other.weekOfYear != null)
				return false;
		} else if (!weekOfYear.equals(other.weekOfYear))
			return false;
		if (title == null) {
			if (other.title != null)
				return false;
		} else if (!title.equals(other.title))
			return false;
		if (year == null) {
			if (other.year != null)
				return false;
		} else if (!year.equals(other.year))
			return false;
		return true;
	}

	@Override
	public String toString() {
		return "Weekly [year=" + year + ", numberOfWeek=" + weekOfYear
				+ ", title=" + title + ", chineseTitle=" + chineseTitle
				+ ", frenchTitle=" + frenchTitle + ", comments=" + comments
				+ ", chineseComments=" + chineseComments + ", frenchComments="
				+ frenchComments + "]";
	}

}
